﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;
using service_desk_blred.Utils;
using MySql.Data.MySqlClient;

namespace service_desk_blred.Models
{
    #region Models
    public class LogOnModel
    {
        [Required(ErrorMessage = "O Campo Nome de Usuário é obrigatório!")]
        [DisplayName("Nome de Usuário")]
        public string Login { get; set; }

        [Required(ErrorMessage = "O Campo senha é obrigatório!")]
        [DataType(DataType.Password)]
        [DisplayName("Senha")]
        public string Senha { get; set; }

    }

    [PropertiesMustMatch("Email", "ConfirmarEmail", ErrorMessage = "Os emails não correspondem.")]
    public class EsqueciSenhaModel
    {
        [Required(ErrorMessage = "O Campo Email é obrigatório!")]
        [DisplayName("Email")]
        public string Email { get; set; }

        [Required(ErrorMessage = "O Campo Confirmar Email é obrigatório!")]
        [DisplayName("Confirmar Email")]
        public string ConfirmarEmail { get; set; }
    }

    [PropertiesMustMatch("NovaSenha", "ConfirmaNovaSenha", ErrorMessage = "Sua nova senha e a confirmação não coincidem.")]
    public class ChangePasswordModel
    {
        [Required]
        [DataType(DataType.Password)]
        [DisplayName("Senha atual")]
        public string SenhaAntiga { get; set; }

        [Required]
        [ValidatePasswordLength]
        [DataType(DataType.Password)]
        [DisplayName("Nova Senha")]
        public string NovaSenha { get; set; }

        [Required]
        [DataType(DataType.Password)]
        [DisplayName("Confirmar nova Senha")]
        public string ConfirmaNovaSenha { get; set; }
    }

    public class UsuarioModel
    {

        public int IdUsuario { get; set; }

        [Required(ErrorMessage = "O Campo Nome de Usuário é obrigatório!")]
        [DisplayName("Nome de Usuário")]
        public string NomeUsuario { get; set; }

        [Required(ErrorMessage = "O Campo Email é obrigatório!")]
        [DataType(DataType.EmailAddress)]
        [DisplayName("Email")]
        public string Email { get; set; }

        [Required(ErrorMessage = "O Campo Telefone é obrigatório!")]
        [DataType(DataType.PhoneNumber)]
        [DisplayName("Telefone")]
        public string Telefone { get; set; }

        [Required(ErrorMessage = "O Campo Celular é obrigatório!")]
        [DataType(DataType.PhoneNumber)]
        [DisplayName("Celular")]
        public string Celular { get; set; }

        [DataType(DataType.PhoneNumber)]
        [DisplayName("Ramal")]
        public string Ramal { get; set; }

        [Required(ErrorMessage = "O Campo Login é obrigatório!")]
        [DisplayName("Login")]
        public string Login { get; set; }

        [DataType(DataType.Password)]
        [DisplayName("Senha")]
        public string Senha { get; set; }

        //Campo utilizado apenas para tratamento na View - Manipulação do Grupo deve ser feita pelo Obj GrupoModel
        [Required(ErrorMessage = "O Campo Grupo precisa ser selecionado!")]
        [DisplayName("Grupo")]
        public string Grupo { get; set; }

        public List<SelectListItem> ListaEstados { get; set; }

        public LocalidadeModel Localidade { get; set; }

        public GrupoModel GrupoUsuario { get; set; }


    }

    public class AnalistaModel
    {

        public UsuarioModel Usuario { get; set; }

        //Campo ListaCargos será utilizado para popular a view de Registro de um Analista
        public List<SelectListItem> ListaCargos { get; set; }

    }

    public class ClienteModel : UsuarioModel
    {

        public UsuarioModel Usuario { get; set; }

        //Campo ListaEmpresa será utilizado para popular a view de Registro de um CLiente
        public List<SelectListItem> ListaEmpresas { get; set; }

        [DisplayName("Gestor da Empresa - Permiti efetuar Compras")]
        public Boolean ClienteGestor { get; set; }

        public EmpresaModel Empresa { get; set; }

    }



    public class GrupoModel
    {


        public int IdGrupo { get; set; }
        public string NomeGrupo { get; set; }

        public int IdRegra { get; set; }
        public string Regra { get; set; }


    }


    public class ListaUsuarioModel
    {
        public ListaUsuarioModel(List<UsuarioModel> list)
        {
            this.usuarios = list;
        }

        public ListaUsuarioModel()
        {
        }

        public List<UsuarioModel> usuarios { get; set; }

        public List<SelectListItem> ListaGrupos { get; set; }

        [DisplayName("Filtrar Grupos")]
        public int idGrupoPesquisa { get; set; }

    }



    #endregion

    #region Services

    public class UsuarioService
    {
        public ResponseInfo ValidarUsuario(string userName, string password)
        {
            if (String.IsNullOrEmpty(userName)) throw new ArgumentException("Value cannot be null or empty.", "userName");
            if (String.IsNullOrEmpty(password)) throw new ArgumentException("Value cannot be null or empty.", "password");

            password = Utils.CriptografaString.encryptString(password);

            String command = "select * from usuario where login = @nomeUsuario and senha = @senha ";

            MySqlCommand cmd = new MySqlCommand();
            cmd.CommandText = command;
            cmd.Parameters.AddWithValue("@nomeUsuario", userName);
            cmd.Parameters.AddWithValue("@senha", password);


            MySqlConnection conn = DataBase.createConnection();
            conn.Open();
            cmd.Connection = conn;

            using (MySqlDataReader dr = cmd.ExecuteReader())
            {
                UsuarioModel model = null;

                while (dr.Read())
                {
                    model = new UsuarioModel();
                    model.IdUsuario = dr.GetInt32("ID_USUARIO");
                    model.NomeUsuario = dr.GetString("NOME_USUARIO");
                    model.Email = dr.GetString("EMAIL");
                    model.Login = dr.GetString("LOGIN");
                    model.Telefone = dr.GetString("TELEFONE");
                    model.Celular = dr.GetString("CELULAR");
                    model.Ramal = dr.GetString("RAMAL");
                    model.Senha = dr.GetString("SENHA");

                    model.GrupoUsuario = new GrupoModel();
                    model.GrupoUsuario.IdGrupo = dr.GetInt32("ID_GRUPO");

                    model.Localidade = new LocalidadeModel();
                    model.Localidade.IdEstado = dr.GetInt32("ID_ESTADO");
                    model.Localidade.Cidade = dr.GetString("CIDADE");

                    return new ResponseInfo(ResponseEntity.Sucesso, "", model);



                }

                if (model == null)
                {
                    return new ResponseInfo(ResponseEntity.Erro, "Senha ou Login Inválido");
                }
            }

            return new ResponseInfo(ResponseEntity.Erro, "Senha ou Login Inválido");
        }

        public ResponseInfo RecuperarUsuarios(Object idGrupo)
        {

            String command = "";
            if (idGrupo != null)
                command = "select * from usuario where ID_GRUPO = @idGrupo";
            else
                command = "select * from usuario";



            MySqlCommand cmd = new MySqlCommand();
            cmd.CommandText = command;

            if (idGrupo != null)
                cmd.Parameters.AddWithValue("@idGrupo", (int)idGrupo);

            MySqlConnection conn = DataBase.createConnection();
            conn.Open();
            cmd.Connection = conn;

            using (MySqlDataReader dr = cmd.ExecuteReader())
            {
                List<UsuarioModel> models = new List<UsuarioModel>();

                while (dr.Read())
                {

                    UsuarioModel model = new UsuarioModel();
                    model.IdUsuario = dr.GetInt32("ID_USUARIO");
                    model.NomeUsuario = dr.GetString("NOME_USUARIO");
                    model.Email = dr.GetString("EMAIL");
                    model.Login = dr.GetString("LOGIN");
                    model.Telefone = dr.GetString("TELEFONE");
                    model.Celular = dr.GetString("CELULAR");
                    model.Ramal = dr.GetString("RAMAL");
                    model.Senha = dr.GetString("SENHA");

                    model.GrupoUsuario = new GrupoModel();
                    model.GrupoUsuario.IdGrupo = dr.GetInt32("ID_GRUPO");

                    model.Localidade = new LocalidadeModel();
                    model.Localidade.IdEstado = dr.GetInt32("ID_ESTADO");
                    model.Localidade.Cidade = dr.GetString("CIDADE");

                    models.Add(model);
                }

                if (models == null)
                {
                    return new ResponseInfo(ResponseEntity.Erro, "Senha ou Login Inválido");
                }
                else
                {
                    return new ResponseInfo(ResponseEntity.Sucesso, "", models);
                }
            }

            return new ResponseInfo(ResponseEntity.Erro, "Senha ou Login Inválido");
        }

        public ResponseInfo CriarUsuario(UsuarioModel model)
        {

            String command = "INSERT INTO USUARIO (NOME_USUARIO,EMAIL,LOGIN,SENHA,TELEFONE,CELULAR,RAMAL,CIDADE,ID_GRUPO,ID_ESTADO)"
                + " VALUES (@nomeUsuario,@email,@login,@senha,@telefone,@celular,@ramal,@cidade,@idGrupo,@idEstado)";

            MySqlCommand cmd = new MySqlCommand();
            cmd.CommandText = command;
            cmd.Parameters.AddWithValue("@nomeUsuario", model.NomeUsuario);
            cmd.Parameters.AddWithValue("@email", model.Email);
            cmd.Parameters.AddWithValue("@login", model.Login);
            cmd.Parameters.AddWithValue("@senha", model.Senha);
            cmd.Parameters.AddWithValue("@telefone", model.Telefone);
            cmd.Parameters.AddWithValue("@celular", model.Celular);
            cmd.Parameters.AddWithValue("@ramal", model.Ramal);
            cmd.Parameters.AddWithValue("@idGrupo", model.GrupoUsuario.IdGrupo);
            cmd.Parameters.AddWithValue("@idEstado", model.Localidade.IdEstado);
            cmd.Parameters.AddWithValue("@cidade", model.Localidade.Cidade);

            try
            {

                if (DataBase.ExecuteNonQuery(cmd) != 0)
                {

                    return new ResponseInfo(ResponseEntity.Sucesso);
                }
                else
                {
                    return new ResponseInfo(ResponseEntity.Erro, "Não foi possível realizar está operação.");
                }

            }

            catch (Exception e)
            {
                return new ResponseInfo(ResponseEntity.Erro, e.Message);
            }
        }

        public ResponseInfo CriarUsuarioCliente(ClienteModel clienteModel)
        {

            UsuarioModel model = clienteModel.Usuario;

            String command = "INSERT INTO USUARIO (NOME_USUARIO,EMAIL,LOGIN,SENHA,TELEFONE,CELULAR,RAMAL,CIDADE,ID_GRUPO,ID_ESTADO)"
                + " VALUES (@nomeUsuario,@email,@login,@senha,@telefone,@celular,@ramal,@cidade,@idGrupo,@idEstado)";

            MySqlCommand cmd = new MySqlCommand();
            cmd.CommandText = command;
            cmd.Parameters.AddWithValue("@nomeUsuario", model.NomeUsuario);
            cmd.Parameters.AddWithValue("@email", model.Email);
            cmd.Parameters.AddWithValue("@login", model.Login);
            cmd.Parameters.AddWithValue("@senha", model.Senha);
            cmd.Parameters.AddWithValue("@telefone", model.Telefone);
            cmd.Parameters.AddWithValue("@celular", model.Celular);
            cmd.Parameters.AddWithValue("@ramal", model.Ramal);
            cmd.Parameters.AddWithValue("@idGrupo", model.GrupoUsuario.IdGrupo);
            cmd.Parameters.AddWithValue("@idEstado", model.Localidade.IdEstado);
            cmd.Parameters.AddWithValue("@cidade", model.Localidade.Cidade);

            try
            {

                if (DataBase.ExecuteNonQuery(cmd) != 0)
                {

                    long clienteId = cmd.LastInsertedId;

                    command = "INSERT INTO EMPRESA_USUARIO (ID_EMPRESA,ID_USUARIO,USUARIO_GESTOR)" +
                        " VALUES (@idEmpresa, @idUsuario, @usuarioGestor)";

                    cmd = new MySqlCommand();
                    cmd.CommandText = command;
                    cmd.Parameters.AddWithValue("@idEmpresa", clienteModel.Empresa.IdEmpresa);
                    cmd.Parameters.AddWithValue("@idUsuario", clienteId);
                    cmd.Parameters.AddWithValue("@usuarioGestor", clienteModel.ClienteGestor);

                    if (DataBase.ExecuteNonQuery(cmd) != 0)
                        return new ResponseInfo(ResponseEntity.Sucesso);
                    else
                        return new ResponseInfo(ResponseEntity.Erro, "Não foi possível realizar está operação.");
                }
                else
                {
                    return new ResponseInfo(ResponseEntity.Erro, "Não foi possível realizar está operação.");
                }

            }

            catch (Exception e)
            {
                return new ResponseInfo(ResponseEntity.Erro, e.Message);
            }
        }

        public ResponseInfo RecuperarGrupos()
        {
            String command = "select ID_GRUPO, NOME_GRUPO, G.ID_REGRA, NOME_REGRA "
                + "from grupo g inner join regra r on g.ID_REGRA = r.ID_REGRA";

            MySqlCommand cmd = new MySqlCommand();
            cmd.CommandText = command;

            MySqlConnection conn = DataBase.createConnection();
            conn.Open();
            cmd.Connection = conn;

            using (MySqlDataReader dr = cmd.ExecuteReader())
            {
                List<GrupoModel> grupos = new List<GrupoModel>();
                while (dr.Read())
                {
                    GrupoModel model = new GrupoModel();

                    model.IdGrupo = dr.GetInt32("ID_GRUPO");
                    model.NomeGrupo = dr.GetString("NOME_GRUPO");
                    model.IdRegra = dr.GetInt32("ID_REGRA");
                    model.Regra = dr.GetString("NOME_REGRA");


                    grupos.Add(model);
                }
                DataBase.closeConnection(conn);
                return new ResponseInfo(ResponseEntity.Sucesso, "", grupos);
            }

        }

        public bool VerificaRecuperacaoDeSenha(String email)
        {
            String command = "select * from usuario where EMAIL = @email";

            MySqlCommand cmd = new MySqlCommand();
            cmd.CommandText = command;
            cmd.Parameters.AddWithValue("@email", email);

            MySqlConnection conn = DataBase.createConnection();
            conn.Open();
            cmd.Connection = conn;

            using (MySqlDataReader dr = cmd.ExecuteReader())
            {
                bool validate = false;

                while (dr.Read())
                {
                    validate = true;
                    break;
                }
                DataBase.closeConnection(conn);
                return validate;
            }

        }




        public bool MudarSenha(UsuarioModel model, string oldPassword, string newPassword)
        {
            if (String.IsNullOrEmpty(oldPassword)) throw new ArgumentException("Value cannot be null or empty.", "oldPassword");
            if (String.IsNullOrEmpty(newPassword)) throw new ArgumentException("Value cannot be null or empty.", "newPassword");

            if (oldPassword.Equals(CriptografaString.encryptString(model.Senha)))
                throw new ArgumentException("Senha antiga não confere");
            else
            {
                String command = "UPDATE usuario SET SENHA = @senha where ID_USUARIO = @idUsuario";
                MySqlCommand cmd = new MySqlCommand();
                cmd.CommandText = command;
                cmd.Parameters.AddWithValue("@senha", Utils.CriptografaString.encryptString(newPassword));
                cmd.Parameters.AddWithValue("@idUsuario", model.IdUsuario);

                try
                {

                    if (DataBase.ExecuteNonQuery(cmd) != 0)
                    {
                        return true;
                    }
                    else
                    {
                        throw new ArgumentException("Erro ao efetuar alteração");
                    }

                }

                catch (Exception e)
                {
                    throw new ArgumentException(e.Message);
                }

            }
        }
    }

    public interface IFormsAuthenticationService
    {
        void SignIn(UsuarioModel userName, bool createPersistentCookie);
        void SignOut();
    }

    public class ControleDeAcessoService : IFormsAuthenticationService
    {
        public void SignIn(UsuarioModel user, bool createPersistentCookie)
        {
            FormsAuthentication.SetAuthCookie(user.NomeUsuario, false);

            if (user.GrupoUsuario.IdGrupo == 1 || user.GrupoUsuario.IdGrupo == 2 || user.GrupoUsuario.IdGrupo == 3)
            {
                if (!Roles.IsUserInRole(user.NomeUsuario, "analista"))

                    Roles.AddUserToRole(user.NomeUsuario, "analista");
            }
            else if (user.GrupoUsuario.IdGrupo == 4)
            {
                if (!Roles.IsUserInRole(user.NomeUsuario, "cliente"))
                {
                    Roles.AddUserToRole(user.NomeUsuario, "cliente");
                }

            }
            else if (user.GrupoUsuario.IdGrupo == 5)
            {
                if (!Roles.IsUserInRole(user.NomeUsuario, "cliente_gestor"))
                {
                    Roles.AddUserToRole(user.NomeUsuario, "cliente_gestor");
                }

            }
            else
            {
                if (!Roles.IsUserInRole(user.NomeUsuario, "gestorti"))
                {
                    Roles.AddUserToRole(user.NomeUsuario, "gestorti");
                }
            }
        }


        public void SignOut()
        {
            FormsAuthentication.SignOut();
        }
    }
    #endregion

}
